#ifndef __SIM_STAT_MANAGER_H__
#define __SIM_STAT_MANAGER_H__

#include "uarch/types.h"
#include "CaffProc/processor.h"
#include "CaffCache/hash_table.h"
#include "CaffMC/memory.h"
//#include "../network/router.h"
//#include "../network/mesh_interface.h"
#include "sim.h"
#include "uarch/enums.h"
#include <string>
#include <ostream>

using namespace std;

class Sim_stat_manager
{
private:
	sim_output_mode_t output_dest;
	string * report_filenames;
	string * dir_name;
	ostream * output_stream;
	int x_dimension;
	int y_dimension;

	/* list of all statistics engines within the system, by type */
	//MAP<int, Processor_stat_engine *> processor_stat_engine_map;
	MAP<int, Hash_table_stat_engine *> L1_stat_engine_map;
	MAP<int, Hash_table_stat_engine *> L2_stat_engine_map;
	MAP<int, Hash_table_stat_engine *> L3_stat_engine_map;
	MAP<int, Memory_controller_stat_engine *> memory_controller_stat_engine_map;
//	MAP<int, Mesh_interface_stat_engine *> mesh_interface_stat_engine_map;
//	MAP<int, Router_stat_engine *> router_stat_engine_map;
	Simulator_stat_engine * simulator_stats;

	/* declarations to store the accumulation of all individual statistic engines */
	//Processor_stat_engine global_processor_stat_engine;
	Hash_table_stat_engine global_L1_stat_engine;
	Hash_table_stat_engine global_L2_stat_engine;
	Hash_table_stat_engine global_L3_stat_engine;
	Memory_controller_stat_engine global_memory_controller_stat_engine;
//	Mesh_interface_stat_engine global_mesh_interface_stat_engine;
//	Router_stat_engine global_router_stat_engine;

public:

	Sim_stat_manager(sim_output_mode_t output_fmt);
	~Sim_stat_manager();

	void save_stats(); //TODO remove me?

	/* output of all system statistics */
	void output_all();

	/* creates the individual, per-node statistics files */
	void output_stats();

	/* output to the system summary */
	void output_global_stats();

//	void output_router_heat_maps(ostream & out);

	/* individual node stat output helper function */
	void output_node_stats(int node);

	/* add statistics engine for management / reduction */
	//void add_processor_engine(int id, Processor_stat_engine * engine);
	void add_L1_engine(int id, Hash_table_stat_engine * engine);
	void add_L2_engine(int id, Hash_table_stat_engine * engine);
	void add_L3_engine(int id, Hash_table_stat_engine * engine);
	void add_memory_controller_engine(int id, Memory_controller_stat_engine * engine);
//	void add_mesh_interface_stat_engine(int id, Mesh_interface_stat_engine * engine);
//	void add_router_stat_engine(int id, Router_stat_engine * engine);
	void add_simulator_stat_engine(Simulator_stat_engine * engine);

	/* aggregate all individual stats into a system summary */
	void merge_all();

	/* clear all statistics in the system */
	void clear_all();

	/* aggregation helper functions */
	//void merge_processor_stats();
	void merge_L1_stats();
	void merge_L2_stats();
	void merge_L3_stats();
	void merge_directory_stats();
	void merge_memory_ctrl_stats();
//	void merge_mesh_stats();
//	void merge_router_stats();

	/* clear helper functions */
	//void clear_processor_stats();
	void clear_L1_stats();
	void clear_L2_stats();
	void clear_L3_stats();
	void clear_directory_stats();
	void clear_memory_ctrl_stats();
//	void clear_mesh_stats();

	void init_filenames();
};

#endif
